#include "Sokoban.h"
#include <stdlib.h>
#include <assert.h>

void  sokInit(Sokoban *pSok, const Terrain *pTer)     
{
	int x,y;
	
	for(y=0;y<getDimY(pTer);y++)
		for(x=0;x<getDimX(pTer);x++)
		{
			if(pTer->tab[y][x]=='$')
			{
				pSok->x=x;
				pSok->y=y;
				
			}
		}
	
	pSok->etat=MARCHE_SOKOBAN;
	pSok->nb_mouvement=0;
}


void sokGauche(Sokoban *pSok, const Terrain *pTer, ListeCaisse *lCai)
{
	Caisse *pCai, *pCaiSuivante;
	int non_mur;
	
	if (terEstPositionSokoValide( pTer, pSok->x-1, pSok->y) && pSok->etat==MARCHE_SOKOBAN)
        {
		pCai=caiRecherche(lCai, pSok->x-1,pSok->y);
		if(pCai)
	       {
			pCaiSuivante=caiRecherche(lCai,pSok->x-2,pSok->y);
			if(pCaiSuivante==NULL)
			{
				caiGauche(pCai,pTer,&non_mur);
				if(non_mur==1)
				{
					pSok->x--;
					pSok->nb_mouvement++;
				}
			}
	       }
		else
	       {
			pSok->x--;
			pSok->nb_mouvement++;
	       }

	}
}

void sokDroite(Sokoban *pSok, const Terrain *pTer, ListeCaisse *lCai)
{
	Caisse *pCai, *pCaiSuivante;
	int non_mur;
	
	if (terEstPositionSokoValide( pTer, pSok->x+1, pSok->y) && pSok->etat==MARCHE_SOKOBAN)
        {
		pCai=caiRecherche(lCai, pSok->x+1,pSok->y);
		if(pCai)
		{
			pCaiSuivante=caiRecherche(lCai, pSok->x+2,pSok->y);
			if(pCaiSuivante==NULL)
			{
				caiDroite( pCai, pTer, &non_mur);
				if(non_mur==1)
				{
					pSok->x++;		  
					pSok->nb_mouvement++;
				}
			}
	       }
		else
		{
			pSok->x++;
			pSok->nb_mouvement++;
		}
	}
}

void sokHaut(Sokoban *pSok, const Terrain *pTer, ListeCaisse *lCai)
{
	Caisse *pCai,*pCaiSuivante;
	int non_mur;
	
	if (terEstPositionSokoValide( pTer, pSok->x, pSok->y-1) && pSok->etat==MARCHE_SOKOBAN)
	{
		pCai=caiRecherche(lCai, pSok->x,pSok->y-1);
		if(pCai)
		{
			pCaiSuivante=caiRecherche(lCai, pSok->x,pSok->y-2);
			if(pCaiSuivante==NULL)
			{
				caiHaut(pCai,pTer,&non_mur);
				if(non_mur==1)
				{
					pSok->y--;		  
					pSok->nb_mouvement++;
				}
			}
		}
		else
		{
			pSok->y--;
			pSok->nb_mouvement++;
		}
	}
 }

void sokBas(Sokoban *pSok, const Terrain *pTer, ListeCaisse *lCai)
{
	
	int non_mur;
	Caisse *pCai, *pCaiSuivante;
	
	if (terEstPositionSokoValide( pTer, pSok->x, pSok->y+1) && pSok->etat==MARCHE_SOKOBAN)
	{
		pCai=caiRecherche(lCai, pSok->x,pSok->y+1);
		if(pCai)
		{
			pCaiSuivante=caiRecherche(lCai, pSok->x,pSok->y+2);
			if(pCaiSuivante==NULL)
			{
				caiBas(pCai,pTer,&non_mur);
				if(non_mur==1)
				{
					pSok->y++;
					pSok->nb_mouvement++;
				}
			}
		}
		else
		{
			pSok->y++;
			pSok->nb_mouvement++;
		}
	    
	}
}

int sokGetX(const Sokoban *pSok)
{
	return pSok->x;
}

int sokGetY(const Sokoban *pSok)
{
	return pSok->y;
}

EtatSokoban sokGetEtat(const Sokoban *pSok)
{
	return pSok->etat;
}

void sokSetEtat(Sokoban *pSok,EtatSokoban nouveau_etat )
{
	pSok->etat=nouveau_etat;	
}

int sokGetNbMouvement(const Sokoban *pSok)
{
	return pSok->nb_mouvement;
}

void sokRazNbMouvement(Sokoban *pSok)
{
	pSok->nb_mouvement=0;
}

void sokTestRegression()
{
	int X,Y;
	
	Sokoban sok;
	Terrain ter;
	ListeCaisse lcai;
	
	char nom_fichier[]="data/niveau/niveau1.txt";
	
	/*!< on initialise le terrain  le sokoban et la  liste de caisse*/
	terInit(&ter, nom_fichier);
	sokInit(&sok, &ter);
	caiInit(&lcai,&ter);
	
	/*!< on deplace le sokoban dans les quatre directions*/
	sokGauche(&sok,&ter,&lcai);
	sokDroite(&sok,&ter,&lcai);
	sokHaut(&sok,&ter,&lcai);
	sokBas(&sok,&ter,&lcai);
	
	/*!<on verifie les coordonnes en x et en y du sokoban*/
	X= sokGetX(&sok);
	Y=sokGetY(&sok);
	assert(X>=0 && X<getDimX(&ter));
	assert(Y>=0 && Y<getDimY(&ter));

	/*!on modifie l'etat du sokoban, puis on fait une verification*/
	sokSetEtat(&sok, STOP_SOKOBAN);
/*	assert(sokGetEtat(&sok)!=STOP_SOKOBAN);*/
	
	/*!< on libere les emplacements alloues pour le terrain et la liste de caisse*/
	terLibere(&ter);
	caiLibere(&lcai); 
}
